﻿using NineSeas.Extensions;
using NineSeas.Models;
using NineSeas.Services;
using NineSeas.ViewModels;
using NineSeas.ViewModels.Admin;
using Orchard.ContentManagement;
using Orchard.Data;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.Security;
using Orchard.Settings;
using Orchard.UI.Admin;
using Orchard.UI.Navigation;
using Orchard.UI.Notify;
using System;
using System.Web.Mvc;
namespace NineSeas.Controllers
{
    [Admin]
    public class BookAdminController : Controller, IUpdateModel
    {
        private dynamic Shape { get; set; }
        private readonly ISiteService _siteService;
        private readonly IBookService _bookService;
        private readonly IContentManager _contentManager;
        private readonly IAuthenticationService _authenticationService;
        private readonly INotifier _notifier;
        private readonly ITransactionManager _transactionManager;
        private readonly IChapterService _chapterService;
        private Localizer T { get; set; }

        public BookAdminController(IShapeFactory shapeFactory,
                ISiteService siteService,
                IContentManager contentManager,
                IBookService bookService,
                INotifier notifier,
                IAuthenticationService authenticationService,
                ITransactionManager transactionManager,
                IChapterService chapterService)
        {
            Shape = shapeFactory;
            _siteService = siteService;
            _bookService = bookService;
            _contentManager = contentManager;
            _authenticationService = authenticationService;
            _notifier = notifier;
            _transactionManager = transactionManager;
            _chapterService = chapterService;
            T = NullLocalizer.Instance;
        }

        public ActionResult Index(BookSearchViewModel search, PaginationInfo paging)
        {
            var viewModel = new BooksViewModel();
            viewModel.Search = search;

            search.SetOptions(new BookSearchViewModel.SearchOptions
            {
                ForEdit = true
            });

            viewModel.Books = _bookService.Search(search, paging, VersionOptions.Latest);

            var pagerShape = Shape.Pager(paging).TotalItemCount(paging.TotalRecords);
            viewModel.Pager = pagerShape;

            return View(viewModel);
        }

        public ActionResult Create(string name)
        {
            var book = _contentManager.New<BookPart>("Book");
            if (book == null)
                return HttpNotFound();

            dynamic model = _contentManager.BuildEditor(book);

            if (!String.IsNullOrWhiteSpace(name))
            {
                book.Name = name;
                book.NameOnUrl = UrlUtilities.UrlFriendlyString(name);
            }
            return View((object)model);
        }

        [ValidateInput(false)]
        [HttpPost, ActionName("Create")]
        public ActionResult CreatePOST()
        {
            var book = _contentManager.New<BookPart>("Book");

            _contentManager.Create(book, VersionOptions.Draft);
            dynamic model = _contentManager.UpdateEditor(book, this);

            book.AuthorId = _authenticationService.GetAuthenticatedUser().Id;

            if (!ModelState.IsValid)
            {
                _transactionManager.Cancel();
                // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
                return View((object)model);
            }

            book.CreatedDate = DateTime.Now;
            book.LastUpdatedDate = DateTime.Now;

            _contentManager.Publish(book.ContentItem);
            _notifier.Information(T("The book has been created. Now please create its content."));
            return Redirect(Url.Action("Chapters", "BookAdmin", new { area = "NineSeas", id = book.Id }));
        }

        public ActionResult Edit(int id)
        {
            var book = _contentManager.Get<BookPart>(id, VersionOptions.Latest);
            var model = _contentManager.BuildEditor(book);

            return View((object)model);
        }

        [ValidateInput(false)]
        [HttpPost, ActionName("Edit")]
        public ActionResult EditPOST(int id)
        {
            var article = _contentManager.Get<BookPart>(id, VersionOptions.DraftRequired);

            if (article == null)
                return HttpNotFound();

            dynamic model = _contentManager.UpdateEditor(article, this);
            if (!ModelState.IsValid)
            {
                _transactionManager.Cancel();
                // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
                return View((object)model);
            }

            article.LastUpdatedDate = DateTime.Now;

            _contentManager.Publish(article.ContentItem);
            _notifier.Information(T("Book updated"));

            return Redirect(Url.Action("Index", "BookAdmin", new { area = "NineSeas" }));
        }

        public ActionResult Chapters(int id, PaginationInfo paging)
        {
            if (id >= 0)
            {
                ViewBag.Book = _contentManager.Get<BookPart>(id);
                ViewBag.Chapters = _chapterService.GetByBookId(id, paging, VersionOptions.Latest);
            }

            ViewBag.Paging = paging;

            return View();
        }

        public ActionResult CreateChapter(int id)
        {
            var chapter = _contentManager.New<ChapterPart>("Chapter");
            chapter.BookId = id;
            ViewBag.Book = _contentManager.Get<BookPart>(id);

            dynamic model = _contentManager.BuildEditor(chapter);
            return View((object)model);
        }

        [ValidateInput(false)]
        [HttpPost, ActionName("CreateChapter")]
        public ActionResult CreateChapterPOST()
        {
            var chapter = _contentManager.New<ChapterPart>("Chapter");

            dynamic model = _contentManager.UpdateEditor(chapter, this);
            _contentManager.Create(chapter, VersionOptions.Draft);
            
            if (!ModelState.IsValid)
            {
                _transactionManager.Cancel();
                // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
                return View((object)model);
            }
            
            _contentManager.Publish(chapter.ContentItem);
            _notifier.Information(T("Chapter created."));
            return Redirect(Url.Action("Chapters", "BookAdmin", new { area = "NineSeas", id = chapter.BookId }));
        }

        public ActionResult EditChapter(int id, int chapterId)
        {
            var chapter = _contentManager.Get<ChapterPart>(chapterId, VersionOptions.Latest);//_chapterService.Get(chapterId);
            var model = _contentManager.BuildEditor(chapter);

            ViewBag.Book = _contentManager.Get<BookPart>(id);

            return View((object)model);
        }

        [ValidateInput(false)]
        [HttpPost, ActionName("EditChapter")]
        public ActionResult EditChapterPOST(int chapterId)
        {
            var chapter = _contentManager.Get<ChapterPart>(chapterId, VersionOptions.DraftRequired);

            dynamic model = _contentManager.UpdateEditor(chapter, this);

            if (!ModelState.IsValid)
            {
                _transactionManager.Cancel();
                // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
                return View((object)model);
            }

            _contentManager.Publish(chapter.ContentItem);
            _notifier.Information(T("Chapter updated."));
            return Redirect(Url.Action("Chapters", "BookAdmin", new { area = "NineSeas", id = chapter.BookId }));
        }

        public ActionResult ChapterMoveUp(int id, int chapterId)
        {
            _chapterService.Move(chapterId, true);
            return Redirect(Url.Action("Chapters", "BookAdmin", new { area = "NineSeas", id = id }));
        }
        public ActionResult ChapterMoveDown(int id, int chapterId)
        {
            _chapterService.Move(chapterId, false);
            return Redirect(Url.Action("Chapters", "BookAdmin", new { area = "NineSeas", id = id }));
        }

        public ActionResult Delete(int id)
        {
            _bookService.Delete(id);
            _notifier.Information(T("Book deleted"));

            return RedirectToAction("Index");
        }

        bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties)
        {
            return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
        }

        void IUpdateModel.AddModelError(string key, LocalizedString errorMessage)
        {
            ModelState.AddModelError(key, errorMessage.Text);
        }
    }
}